﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

namespace GameJam2012
{
    public class LevelManager
    {
        List<Level> levels = new List<Level>();
        List<LevelData> levelData = new List<LevelData>();
        float xOffset = 0;
        float offsetVelocity;
        float offsetFriction = .94f;
        float backgroundOffset = 0f;
        float parallax = .1f;

        protected Entity tracking;
        protected static float RIGHT_TRACKING = .4f; //how far across the screen to start moving the camera with the player
        protected static float LEFT_TRACKING = .25f;

        public GameController GameController;

        public LevelManager(GameController gameController)
        {
            GameController = gameController;
        }

        public void Initialize()
        {
            using (StreamReader r = new StreamReader("levels/levels.txt"))
            {
                String line;

                while ((line = r.ReadLine()) != null)
                {
                    if (line == "end") break;
                    LevelData d = new LevelData();
                    if (d.LoadLevel(line))
                        levelData.Add(d);
                }
            }
        }

        public void PushLevel(Level level)
        {
            if (levels.Count > 0)
            {
                levels[levels.Count - 1].NextLevel = level;
                level.PreviousLevel = levels[levels.Count - 1]; 
            }
            levels.Add(level);
        }

        public void TrackEntity(Entity entity)
        {
            tracking = entity;
        }

        public void Update(GameTime gameTime)
        {
            if (tracking == null || tracking.Dead)
                GameController.Initialize();
            //if (Keyboard.GetState().IsKeyDown(Keys.Left))
            //    xOffset += 5;

            if (tracking != null && tracking.ScreenPosition.X >= SnakeGame.SCREEN_WIDTH * RIGHT_TRACKING)
            {
                if (levels.Count > 1)
                {
                    offsetVelocity -= 1.25f;
                }
            }

            if (tracking != null && tracking.ScreenPosition.X <= SnakeGame.SCREEN_WIDTH * LEFT_TRACKING)
                offsetVelocity = 0; //so the left side of the screen doesn't eat the player

            backgroundOffset = (backgroundOffset + offsetVelocity * parallax) % (SnakeGame.BACKTILE.Width);
            xOffset += offsetVelocity;
            offsetVelocity *= offsetFriction;
            if (offsetVelocity >= -.5f) offsetVelocity = 0;

            //first level is completely offscreen now
            if (xOffset <= -levels[0].ScreenWidth)
            {
                xOffset += levels[0].ScreenWidth;
                levels.RemoveAt(0);
                levels[0].PreviousLevel = null;
            }
            levels[0].LeftBound = -xOffset;
            
            while (levels.Count == 1 || LevelsScreenWidth() <= SnakeGame.SCREEN_WIDTH)
                PushLevel(new Level(levelData[SnakeGame.Random.Next(levelData.Count)]));

            foreach (Level level in levels)
            {
                level.Update(gameTime);
            }
        }

        /// <summary>
        /// Calculates and returns the total on-screen width of all loaded levels
        /// </summary>
        /// <returns>The width in pixels</returns>
        protected int LevelsScreenWidth()
        {
            int total = (int)xOffset;
            foreach (Level level in levels)
            {
                total += level.ScreenWidth;
            }
            return total;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(SnakeGame.BACKTILE, Vector2.Zero, new Rectangle((int)-backgroundOffset, 0, SnakeGame.SCREEN_WIDTH, SnakeGame.SCREEN_HEIGHT), Color.White, 0f, Vector2.Zero, new Vector2(2, 1), SpriteEffects.None, 0f); 
            float xOffsetModifier = 0;
            foreach (Level level in levels)
            {
                level.Draw(spriteBatch, xOffset + xOffsetModifier, 0);
                xOffsetModifier += level.ScreenWidth;
            }
            //spriteBatch.DrawString(SnakeGame.FONT, "X Offset: " + xOffset + "\nLevels Open: " + levels.Count, Vector2.Zero, Color.White, 0f, Vector2.Zero, .75f, SpriteEffects.None, 1f);
            //spriteBatch.DrawString(SnakeGame.FONT, "Left Bound: " + levels[0].LeftBound, new Vector2(0, 690), Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.None, 1f);
        }
    }
}
